#ifndef QTSTRA_USERDATA_H
#define QTSTRA_USERDATA_H
#pragma once
#include "nonqtmain.h"





template <class T>
class QtStraUserdataCore
{
public:
	typedef struct QtStraData
	{
		BarInfo bar;

		T userdata;
	}QtStraData;


	QtStraUserdataCore(){};

	~QtStraUserdataCore(){};


	void SetOld(vector<QtStraData>& data)
	{
		m_stradata_vold = data;
	}

	vector<QtStraData> GetOld()
	{
		return m_stradata_vold;
	};

	void SetNew(vector<QtStraData>& data)
	{
		m_stradata_vnew = data;
	}


	vector<QtStraData> GetNew()
	{
		return m_stradata_vnew;
	}

	void AddNew(QtStraData& data)
	{
		m_stradata_vnew.push_back(data);
	}


	bool AddInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);
	bool DelInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);
	bool EditInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);

public:



private:


	vector<QtStraData> m_stradata_vold;
	vector<QtStraData> m_stradata_vnew;


};



//
template <class T>
bool QtStraUserdataCore<T>::DelInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata)
{

	typedef vector<QtStraData>::iterator it_vstra2;


	/*****************Update vdel*********************************************/
	for (it_vstra2 itold = m_stradata_vold.begin(); itold != m_stradata_vold.end(); itold++)
	{
		BarInfo& oldbar = (*itold).bar;
		T& userdata = (*itold).userdata;
		bool bfound = false;

		for (it_vstra2 itnew = m_stradata_vnew.begin(); itnew != m_stradata_vnew.end(); itnew++)
		{
			BarInfo& newbar = (*itnew).bar;
			if (0 == memcmp(&oldbar, &newbar, sizeof(BarInfo)))
			{
				bfound = true;
				break;
			}
		}

		//not found, it's deleted, so add to vpmfcdata for del
		if (false == bfound)
		{
			//new memory
			MFCData* pmfcdata;
			pmfcdata = new MFCData();
			if (NULL == pmfcdata)
			{
				pantheios::log_ERROR("[QtStraTemplate::MFCData_DelInst] pmfcdata(add) NULL");
				return false;
			}

			//set del MFCData info
			pmfcdata->type = MFC_namespace::del;
			memcpy(&pmfcdata->bar, &oldbar, sizeof(BarInfo));//deep copy
			pmfcdata->timertype = timertype;
			pmfcdata->varsize = 0;
			pmfcdata->pvardata = NULL;

			//copy into vpmfcdata
			vpmfcdata.push_back(pmfcdata);
		}

	}

	/************************************************************************/


	return true;

}


template <class T>
bool QtStraUserdataCore<T>::AddInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata)
{

	typedef vector<QtStraData>::iterator it_vstra2;


	/*****************Update vadd*********************************************/
	for (it_vstra2 itnew = m_stradata_vnew.begin(); itnew != m_stradata_vnew.end(); itnew++)
	{
		BarInfo& newbar = (*itnew).bar;
		T& userdata =  (*itnew).userdata;
		bool bfound = false;

		for (it_vstra2 itold = m_stradata_vold.begin(); itold != m_stradata_vold.end(); itold++)
		{
			BarInfo& oldbar = (*itold).bar;
			if (0 == memcmp(&oldbar, &newbar, sizeof(BarInfo)))
			{
				bfound = true;
				break;
			}
		}

		//not found, it's added, so add to vpmfcdata for add
		if (false == bfound)
		{
			//new memory
			MFCData* pmfcdata;
			pmfcdata = new MFCData();
			if (NULL == pmfcdata)
			{
				pantheios::log_ERROR("[QtStraTemplate::MFCData_AddInst] pmfcdata(add) NULL");
				return false;
			}

			//set add MFCData info
			pmfcdata->type = MFC_namespace::add;
			memcpy(&pmfcdata->bar, &newbar, sizeof(BarInfo));//deep copy
			pmfcdata->timertype = timertype;
			pmfcdata->varsize = sizeof(T);
			pmfcdata->pvardata = (char*)new T();
			if (NULL == pmfcdata->pvardata)//user data is also new
			{
				pantheios::log_ERROR("[QtStraTemplate::MFCData_AddInst] pmfcdata->pvardata(add) NULL");
				return false;
			}
			memcpy(pmfcdata->pvardata, (char*)(&userdata), sizeof(T));//deep copy


			//copy into vpmfcdata
			vpmfcdata.push_back(pmfcdata);

		}

	}
	/************************************************************************/


	return true;

}


template <class T>
bool QtStraUserdataCore<T>::EditInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata)
{

	typedef vector<QtStraData>::iterator it_vstra2;


	/*****************Update vadd*********************************************/
	for (it_vstra2 itnew = m_stradata_vnew.begin(); itnew != m_stradata_vnew.end(); itnew++)
	{
		BarInfo& newbar = (*itnew).bar;
		T& new_userdata =  (*itnew).userdata;
		bool bfound = false;

		for (it_vstra2 itold = m_stradata_vold.begin(); itold != m_stradata_vold.end(); itold++)
		{
			BarInfo& oldbar = (*itold).bar;
			T& old_userdata =  (*itold).userdata;
			if (0 == memcmp(&oldbar, &newbar, sizeof(BarInfo)))
			{
				if (0 != memcmp(&new_userdata, &old_userdata, sizeof(T)))	//userdata not changed
				{
					bfound = true;
					break;
				}		

			}
		}

		//not found, it's added, so add to vpmfcdata for add
		if (true == bfound)
		{
			//new memory
			MFCData* pmfcdata;
			pmfcdata = new MFCData();
			if (NULL == pmfcdata)
			{
				pantheios::log_ERROR("[QtStraTemplate::MFCData_EditInst] pmfcdata(add) NULL");
				return false;
			}

			//set edit MFCData info
			pmfcdata->type = MFC_namespace::edit;
			memcpy(&pmfcdata->bar, &newbar, sizeof(BarInfo));//deep copy
			pmfcdata->timertype = timertype;
			pmfcdata->varsize = sizeof(T);
			pmfcdata->pvardata = (char*)new T();
			if (NULL == pmfcdata->pvardata)//user data is also new
			{
				pantheios::log_ERROR("[QtStraTemplate::MFCData_EditInst] pmfcdata->pvardata(add) NULL");
				return false;
			}
			memcpy(pmfcdata->pvardata, (char*)(&new_userdata), sizeof(T));//deep copy


			//copy into vpmfcdata
			vpmfcdata.push_back(pmfcdata);

		}

	}
	/************************************************************************/


	return true;

}


class QtStraUserdata
{

public:
	QtStraUserdata(int straindex);

	~QtStraUserdata(){};


	//void SetOld(vector<QtStraUserdataCore<userdata_stra1>::QtStraData>& data){ m_pstra1userdata->SetOld(data); };
	//void SetOld(vector<QtStraUserdataCore<userdata_stra2>::QtStraData>& data){ m_pstra2userdata->SetOld(data); };
	//void SetOld(vector<QtStraUserdataCore<userdata_stra3>::QtStraData>& data){ m_pstra3userdata->SetOld(data); };

	//void GetOld(vector<QtStraUserdataCore<userdata_stra1>::QtStraData>& data){ data = m_pstra1userdata->GetOld(); };
	//void GetOld(vector<QtStraUserdataCore<userdata_stra2>::QtStraData>& data){ data = m_pstra2userdata->GetOld(); };
	//void GetOld(vector<QtStraUserdataCore<userdata_stra3>::QtStraData>& data){ data = m_pstra3userdata->GetOld(); };


	//void SetNew(vector<QtStraUserdataCore<userdata_stra1>::QtStraData>& data){ m_pstra1userdata->SetNew(data); };
	//void SetNew(vector<QtStraUserdataCore<userdata_stra2>::QtStraData>& data){ m_pstra2userdata->SetNew(data); };
	//void SetNew(vector<QtStraUserdataCore<userdata_stra3>::QtStraData>& data){ m_pstra3userdata->SetNew(data); };

	//void GetNew(vector<QtStraUserdataCore<userdata_stra1>::QtStraData>& data){ data = m_pstra1userdata->GetNew(); };
	//void GetNew(vector<QtStraUserdataCore<userdata_stra2>::QtStraData>& data){ data = m_pstra2userdata->GetNew(); };
	//void GetNew(vector<QtStraUserdataCore<userdata_stra3>::QtStraData>& data){ data = m_pstra3userdata->GetNew(); };


	void SetOldFromNew();

	void ClearNew();

	void AddNew(QtStraUserdataCore<userdata_stra1>::QtStraData& data);
	void AddNew(QtStraUserdataCore<userdata_stra2>::QtStraData& data);
	void AddNew(QtStraUserdataCore<userdata_stra3>::QtStraData& data);


	void SwapOldAndNew();

	bool AddInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);
	bool DelInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);
	bool EditInst(TimerFire_namespace::TimerFireType timertype, vector<MFCData*>& vpmfcdata);

private:
	//from 1
	int m_straindex;

	QtStraUserdataCore<userdata_stra1>* m_pstra1userdata;

	QtStraUserdataCore<userdata_stra2>* m_pstra2userdata;

	QtStraUserdataCore<userdata_stra3>* m_pstra3userdata;
};



#endif